package com.ziyun.erp.web.modules.invoice.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.ziyun.erp.common.e.DeleteEnum;
import com.ziyun.erp.common.e.invoice.TaxClassifyEnum;
import com.ziyun.erp.common.e.invoice.TaxStatusEnum;
import com.ziyun.erp.common.e.order.PayStatusEnum;
import com.ziyun.erp.common.e.order.TaxTypeEnum;
import com.ziyun.erp.common.utils.JsonUtils;
import com.ziyun.erp.modules.invoice.entity.OrderInvoiceEntity;
import com.ziyun.erp.modules.invoice.entity.OrderInvoiceRelevancyEntity;
import com.ziyun.erp.modules.invoice.service.OrderInvoiceRelevancyService;
import com.ziyun.erp.modules.invoice.service.OrderInvoiceService;
import com.ziyun.erp.modules.order.entity.OrderInfoEntity;
import com.ziyun.erp.modules.order.vo.OrderInfoVo;
import com.ziyun.erp.modules.order.service.OrderInfoService;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.modules.sys.entity.SysUserEntity;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 发票信息表
 *
 * @author gaosheng
 * @email 
 * @date 2018-08-25 15:13:13
 */
@RestController
@RequestMapping("invoice/orderinvoice")
public class OrderInvoiceController {
    @Autowired
    private OrderInvoiceService orderInvoiceService;
    @Autowired
    private OrderInvoiceRelevancyService orderInvoiceRelevancyService;
    @Autowired
    private OrderInfoService orderInfoService;

    /**
     * 订单开票登记列表
     */
    @RequestMapping("/orderInvoiceRegisterList")
    @RequiresPermissions("invoice:orderinvoice:list")
    public R orderInvoiceRegisterList(@RequestParam Map<String, Object> params){
        PageUtils page = orderInvoiceService.queryPageOrderInvoiceRegisterList(params);

        // 存放枚举类到userdata
        Map<String, List> mapEnum = new HashMap<>();
        mapEnum.put("payStatusEnum", JsonUtils.enumToList(PayStatusEnum.class));
        mapEnum.put("taxTypeEnum", JsonUtils.enumToList(TaxTypeEnum.class));

        R r = R.ok();
        r.put("page", page);
        r.put("userData", mapEnum);
        return r;
    }

    /**
     * 订单已开发票列表
     * @param params
     * @return
     */
    @RequestMapping("/orderInvoiceList")
    @RequiresPermissions("invoice:orderinvoice:list")
    public R orderInvoiceList(@RequestParam Map<String, Object> params){
        PageUtils page = orderInvoiceService.queryPageOrderInvoiceList(params);

        // 存放枚举类到userdata
        Map<String, List> mapEnum = new HashMap<>();
        mapEnum.put("taxClassifyEnum", JsonUtils.enumToList(TaxClassifyEnum.class));
        mapEnum.put("taxTypeEnum", JsonUtils.enumToList(TaxTypeEnum.class));
        mapEnum.put("taxStatusEnum", JsonUtils.enumToList(TaxStatusEnum.class));

        R r = R.ok();
        r.put("page", page);
        r.put("userData", mapEnum);
        return r;
    }

    /**
     * 登记发票验证
     * @param orderId 订单号（多个逗号分隔）
     * @return
     */
    @RequestMapping("/orderInvoiceVerify")
    public R orderInvoiceVerify(@RequestParam("orderId") String orderId){
        if (StringUtils.isBlank(orderId)){
            return R.error("请求参数为空！");
        }

        // 订单总金额
        BigDecimal orderMoneyTotal = BigDecimal.ZERO;
        // 已开票总金额
        BigDecimal taxMoneyTotal = BigDecimal.ZERO;
        String[] orderIds = StringUtils.split(orderId, ",");
        List<OrderInfoVo> orderInfoVoList = new ArrayList<>(orderIds.length);
        for (String id : orderIds){
            OrderInfoEntity orderInfoEntity = orderInfoService.selectById(id);
            BigDecimal payableAmount = orderInfoEntity.getPayableAmount();
            orderMoneyTotal = orderMoneyTotal.add(payableAmount);

            List<OrderInvoiceRelevancyEntity> orderInvoiceRelevancyEntities = orderInvoiceRelevancyService.selectList(
                    new EntityWrapper<>(new OrderInvoiceRelevancyEntity())
                            .where(true,"oir_order_id = {0}", id)
                            .where(true,"oir_del = {0}", DeleteEnum.NOT_DELETE.toInt())
            );

            if (orderInvoiceRelevancyEntities.size() > 0){
                BigDecimal reduce = orderInvoiceRelevancyEntities.stream()
                        .map(OrderInvoiceRelevancyEntity::getOirOrderTaxMoney)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                taxMoneyTotal = taxMoneyTotal.add(reduce);

                int compare = payableAmount.compareTo(reduce);
                if (compare <= 0){
                    return R.error("订单号:" + id + "，已开票金额已满！");
                }
            }

            OrderInfoVo orderInfoVo = new OrderInfoVo();
            orderInfoVo.setOrderId(id);
            orderInfoVo.setPayableAmount(payableAmount);
            orderInfoVoList.add(orderInfoVo);
        }

        return  R.ok().put("list", orderInfoVoList).put("amount", orderMoneyTotal);
    }

    /**
     * 多开登记验证
     * @param orderId 订单号（多个逗号分隔）
     * @return
     */
    @RequestMapping("/orderInvoiceMultiVerify")
    public R orderInvoiceMultiVerify(@RequestParam("orderId") String orderId){
        if (StringUtils.isBlank(orderId)){
            return R.error("请求参数为空！");
        }

        String[] orderIds = StringUtils.split(orderId, ",");
        List<OrderInvoiceEntity> list = orderInvoiceService.selectList(
                new EntityWrapper<>(new OrderInvoiceEntity())
                        .in("oi_order_ids", orderIds)
                        .where("oi_del = {0}", DeleteEnum.NOT_DELETE.toInt())
        );

        //验证成功条件:
        //1.当前订单没有开票记录；
        //2.有开票记录，开票分类是4 （多开发票）
        if (list != null && list.size() > 0){
            // 存在开票记录
            long count = list.stream().filter(
                    item -> Integer.compare(item.getOiTaxClassify().intValue(), TaxClassifyEnum.MANY_TO_MANY_4.toInt()) != 0
            ).count();
            if (count > 0){
                return R.error("勾选订单已开票，不允许多开登记！");
            }
        }

        // 订单总金额
        BigDecimal orderMoneyTotal = BigDecimal.ZERO;
        List<OrderInfoVo> orderInfoVoList = new ArrayList<>(orderIds.length);
        for (String id : orderIds){
            OrderInfoEntity orderInfoEntity = orderInfoService.selectById(id);
            BigDecimal payableAmount = orderInfoEntity.getPayableAmount();
            orderMoneyTotal = orderMoneyTotal.add(payableAmount);

            OrderInfoVo orderInfoVo = new OrderInfoVo();
            orderInfoVo.setOrderId(id);
            orderInfoVo.setPayableAmount(payableAmount);
            orderInfoVoList.add(orderInfoVo);
        }

        return R.ok().put("list", orderInfoVoList).put("amount", orderMoneyTotal);
    }


    /**
     *  登记发票录入
     *  判断发票类型,发票数对订单数
     * 1.一对一开票 : 开票订单号只有一个，该订单号没有开票记录，开票金额 == 订单销售金额
     * 2.一对多开票 : 开票订单号有多个，所有订单号没有开票记录，开票金额 == 订单销售金额合计
     * 3.多对一开票 :
     *      1）开票订单号只有一个，该订单号没有开票记录，开票金额 < 订单销售金额；
     *      2）开票订单号只有一个，该订单号有开票记录（且该发票类型是 多对一开票），开票金额 <= 订单销售金额
     * 4.多对多开票 : 其他情况全未多对多开票 （多开发票）
     *
     * @param orderInvoice
     * @return
     */
    @RequestMapping("/saveInvoice")
    public R saveInvoice(@RequestBody OrderInvoiceEntity orderInvoice){
        if (StringUtils.isBlank(orderInvoice.getOiTaxId())){
            return R.error("开票号不能为空！");
        }
        if (orderInvoice.getOiTaxMoney() == null){
            return R.error("开票金额不能为空！");
        }
        if (StringUtils.isBlank(orderInvoice.getOiOrderIds())){
            return R.error("开票订单号不能为空！");
        }

        // 检查发票号是否重复录入
        int count = orderInvoiceService.selectCount(
                new EntityWrapper<>(new OrderInvoiceEntity())
                        .where("oi_tax_id = {0}", orderInvoice.getOiTaxId())
        );
        if (count > 0){
            return R.error("发票号:" + orderInvoice.getOiTaxId() + " 已登记！");
        }

        // 发票录入订单号
        String[] oiOrderIds = orderInvoice.getOiOrderIds().split(",");
        // 发票订单关联信息
        List<OrderInvoiceRelevancyEntity> orderInvoiceRelevancyList = new ArrayList<>(oiOrderIds.length);
        if (oiOrderIds.length == 1){
            // 一对一开票 或者 多对一开票
            String orderId = oiOrderIds[0];
            OrderInfoEntity orderInfo = orderInfoService.selectById(orderId);
            // 发票订单总额
            orderInvoice.setOiOrderTotalMoney(orderInfo.getPayableAmount().toString());
            // 开票记录
            List<OrderInvoiceEntity> orderInvoiceList = orderInvoiceService.selectList(
                    new EntityWrapper<>(new OrderInvoiceEntity())
                            .like("oi_order_ids", orderId)
            );
            if (orderInvoiceList == null || orderInvoiceList.size() <= 0) {
                int compare = orderInfo.getPayableAmount().compareTo(orderInvoice.getOiTaxMoney());
                if (compare == 0){
                    // 1.一对一开票 : 开票订单号只有一个，该订单号没有开票记录，开票金额 == 订单销售金额
                    orderInvoice.setOiTaxClassify(TaxClassifyEnum.ONE_TO_ONE_1.toInt());
                }else if (compare > 0){
                    // 3.多对一开票 : 1）开票订单号只有一个，该订单号没有开票记录，开票金额 < 订单销售金额
                    orderInvoice.setOiTaxClassify(TaxClassifyEnum.MANY_TO_ONE_3.toInt());
                }
            }else {
                // 3.多对一开票 :2）开票订单号只有一个，该订单号有开票记录（且该发票类型是 多对一开票），开票金额 <= 订单销售金额
                for (OrderInvoiceEntity item : orderInvoiceList){
                    if (item.getOiTaxClassify().intValue() != TaxClassifyEnum.MANY_TO_ONE_3.toInt()){
                        return R.error("发票分类异常，开票失败！");
                    }
                }
            }

            // 发票订单关联信息
            OrderInvoiceRelevancyEntity orderInvoiceRelevancy = new OrderInvoiceRelevancyEntity();
            orderInvoiceRelevancy.setOirOrderId(orderId);
            orderInvoiceRelevancy.setOirTaxId(orderInvoice.getOiTaxId());
            orderInvoiceRelevancy.setOirOrderTaxMoney(orderInvoice.getOiTaxMoney());
            orderInvoiceRelevancyList.add(orderInvoiceRelevancy);
        }else {
            // 2.一对多开票 : 开票订单号有多个，所有订单号没有开票记录，开票金额 == 订单销售金额合计
            BigDecimal orderTotalMoney = BigDecimal.ZERO;
            for (String id : oiOrderIds){
                OrderInfoEntity orderInfo = orderInfoService.selectById(id);
                int selectCount = orderInvoiceRelevancyService.selectCount(
                        new EntityWrapper<>(new OrderInvoiceRelevancyEntity())
                                .where("oir_order_id = {0}", id)
                                .where("oir_del = {0}", DeleteEnum.NOT_DELETE.toInt())
                );
                if (selectCount > 0){
                    return R.error("订单号：" + id + "，已开票！");
                }

                orderTotalMoney = orderTotalMoney.add(orderInfo.getPayableAmount());

                // 发票订单关联信息
                OrderInvoiceRelevancyEntity orderInvoiceRelevancy = new OrderInvoiceRelevancyEntity();
                orderInvoiceRelevancy.setOirOrderId(id);
                orderInvoiceRelevancy.setOirTaxId(orderInvoice.getOiTaxId());
                orderInvoiceRelevancy.setOirOrderTaxMoney(orderInfo.getPayableAmount());
                orderInvoiceRelevancyList.add(orderInvoiceRelevancy);
            }
            orderInvoice.setOiOrderTotalMoney(orderTotalMoney.toString());
            orderInvoice.setOiTaxClassify(TaxClassifyEnum.ONE_TO_MANY_2.toInt());
        }

        // 获取当前登陆用户ID
        Long userId = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUserId();
        orderInvoice.setOiCreateBy(userId.toString());

        orderInvoiceService.saveInvoice(orderInvoice, orderInvoiceRelevancyList);

        return R.ok();
    }

    /**
     * 多开登记发票录入
     * @param orderInvoice
     * @return
     */
    @RequestMapping("/saveInvoiceMulti")
    public R saveInvoiceMulti(@RequestBody OrderInvoiceEntity orderInvoice){
        if (StringUtils.isBlank(orderInvoice.getOiTaxId())){
            return R.error("开票号不能为空！");
        }
        if (orderInvoice.getOiTaxMoney() == null){
            return R.error("开票金额不能为空！");
        }
        if (StringUtils.isBlank(orderInvoice.getOiOrderIds())){
            return R.error("开票订单号不能为空！");
        }

        // 检查发票号是否重复录入
        int count = orderInvoiceService.selectCount(
                new EntityWrapper<>(new OrderInvoiceEntity())
                        .where("oi_tax_id = {0}", orderInvoice.getOiTaxId())
        );
        if (count > 0){
            return R.error("发票号:" + orderInvoice.getOiTaxId() + " 已登记！");
        }

        String[] orderIds = orderInvoice.getOiOrderIds().split(",");
        // 发票订单关联信息
        List<OrderInvoiceRelevancyEntity> orderInvoiceRelevancyList = new ArrayList<>(orderIds.length);
        for (String id : orderIds) {
            // 发票订单关联信息
            OrderInvoiceRelevancyEntity orderInvoiceRelevancy = new OrderInvoiceRelevancyEntity();
            orderInvoiceRelevancy.setOirOrderId(id);
            orderInvoiceRelevancy.setOirTaxId(orderInvoice.getOiTaxId());
            orderInvoiceRelevancy.setOirOrderTaxMoney(BigDecimal.ZERO);
            orderInvoiceRelevancyList.add(orderInvoiceRelevancy);
        }

        orderInvoice.setOiOrderTotalMoney("0");
        orderInvoice.setOiTaxClassify(TaxClassifyEnum.MANY_TO_MANY_4.toInt());
        orderInvoiceService.saveInvoice(orderInvoice, orderInvoiceRelevancyList);

        return R.ok();
    }

    /**
     * 发票提交
     * @param oiId 发票ID
     * @return
     */
    @RequestMapping("/sumbitInvoice")
    public R sumbitInvoice(@RequestParam("oiId") Integer oiId){
        OrderInvoiceEntity orderInvoice = orderInvoiceService.selectById(oiId);
        if (orderInvoice == null){
            return R.error("未查询到发票信息！");
        }

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("oiTaxStatus", TaxStatusEnum.UNDER_APPROVAL_1.toInt());
        orderInvoiceService.sumbitInvoice(updateMap, oiId);

        return R.ok();
    }

    /**
     * 发票审核
     * @param oiId 发票ID
     * @return
     */
    @RequestMapping("/auditInvoice")
    public R auditInvoice(@RequestParam("oiId") Integer oiId){
        OrderInvoiceEntity orderInvoice = orderInvoiceService.selectById(oiId);
        if (orderInvoice == null){
            return R.error("未查询到发票信息！");
        }

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("oiTaxStatus", TaxStatusEnum.AUDITED_2.toInt());
        orderInvoiceService.auditInvoice(updateMap, oiId);

        return R.ok();
    }

    /**
     * 发票删除
     * @param oiId 发票ID
     * @return
     */
    @RequestMapping("/deleteInvoice")
    public R deleteInvoice(@RequestParam("oiId") Integer oiId){
        OrderInvoiceEntity orderInvoice = orderInvoiceService.selectById(oiId);
        if (orderInvoice == null){
            return R.error("未查询到发票信息！");
        }
        if (orderInvoice.getOiTaxStatus().intValue() != TaxStatusEnum.TO_BE_SUBMITTED_0.toInt()){
            return R.error("订单已审核！");
        }

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("oiDel", DeleteEnum.DELETE.toInt());
        orderInvoiceService.deleteInvoice(updateMap, oiId);

        return R.ok();
    }

}
